package it.bifulco.luigi.motiondetection.jmftest;

import java.awt.Dimension;
import java.util.Random;

import javax.media.Buffer;
import javax.media.Effect;
import javax.media.Format;
import javax.media.ResourceUnavailableException;
import javax.media.format.RGBFormat;
import javax.media.format.VideoFormat;

public class SimpleFilter implements Effect {
	protected Format inputFormat = null;
	protected Format outputFormat = null;

	protected Format[] inputFormats = null;
	protected Format[] outputFormats = null;
	private int k;

	public SimpleFilter() {
		inputFormats = new Format[] { new RGBFormat(null, Format.NOT_SPECIFIED,
				Format.byteArray, Format.NOT_SPECIFIED, 24, 3, 2, 1, 3,
				Format.NOT_SPECIFIED, Format.TRUE, Format.NOT_SPECIFIED) };

		outputFormats = new Format[] { new RGBFormat(null,
				Format.NOT_SPECIFIED, Format.byteArray, Format.NOT_SPECIFIED,
				24, 3, 2, 1, 3, Format.NOT_SPECIFIED, Format.TRUE,
				Format.NOT_SPECIFIED) };
	}

	/****** Codec ******/
	public Format[] getSupportedInputFormats() {
		return inputFormats;
	}

	public Format[] getSupportedOutputFormats(Format input) {
		if (input == null) {
			return outputFormats;
		}

		if (matches(input, inputFormats) != null) {
			return new Format[] { outputFormats[0].intersects(input) };
		} else {
			return new Format[0];
		}
	}

	byte[] validateByteArraySize(Buffer buffer, int newSize) {
		Object objectArray = buffer.getData();
		byte[] typedArray;

		if (objectArray instanceof byte[]) { // is correct type AND not null
			typedArray = (byte[]) objectArray;
			if (typedArray.length >= newSize) { // is sufficient capacity
				return typedArray;
			}

			byte[] tempArray = new byte[newSize]; // re-alloc array
			System.arraycopy(typedArray, 0, tempArray, 0, typedArray.length);
			typedArray = tempArray;
		} else {
			typedArray = new byte[newSize];
		}

		buffer.setData(typedArray);
		return typedArray;
	}

	public int process(Buffer input, Buffer output) {
		int outputDataLength = ((VideoFormat) outputFormat).getMaxDataLength();

		validateByteArraySize(output, outputDataLength);

		output.setLength(outputDataLength);
		output.setFormat(outputFormat);
		output.setFlags(input.getFlags());

		byte[] inData = (byte[]) input.getData();
		byte[] outData = (byte[]) output.getData();

		RGBFormat vfIn = (RGBFormat) input.getFormat();

		byte result;

		byte[] results = new byte[outData.length];
		k = k + 1;
		for (int i = 0; i < inData.length; i++) {
			// int rgb = inData[i];
			// int r = (rgb >> 16) & 0x000000FF;
			// int g = (rgb >> 8) & 0x000000FF;
			// int b = (rgb) & 0x000000FF;

			// result = (byte) (java.lang.Math
			// .sqrt((double) ((r * r) + (g * g) + (b * b)) / 3.0));

			// LIGHTNESS: /* (max(R, G, B) + min(R, G, B)) / 2. */
			// int max = Math.max(r, g);
			// max = Math.max(max, b);
			// int min = Math.min(r, g);
			// min = Math.min(min, b);
			// int tmp = (max + min / 2);
			//
			// // AVERAGE: /* (R + G + B) / 3 */
			// tmp += (r + g + b / 3);
			//
			// // LUMINOSITY 0.21 R + 0.71 G + 0.07 B

			// results[i] = (byte) tmp;

			int rgb = inData[i];
			int r = (rgb >> 16) & 0x000000FF;
			int g = (rgb >> 8) & 0x000000FF;
			int b = (rgb) & 0x000000FF;

			// r = (int) (r * 0.299);
			// g = (int) (g * 0.587);
			// b = (int) (b * 0.114);

			int max = Math.max(r, g);
			max = Math.max(max, b);
			int min = Math.min(r, g);
			min = Math.min(min, b);
			int tmp = (max + min / 2);

			int lum = 50;

			r = (int) (tmp * 0.299);
			b = (int) (tmp * 0.114);
			g = (int) (tmp * 0.587);
			results[i] = (byte) (r + b + g);

		}

		System.arraycopy(results, 0, outData, 0, inData.length);
		return BUFFER_PROCESSED_OK;
	}

	public Format setInputFormat(Format input) {
		inputFormat = input;

		return input;
	}

	public Format setOutputFormat(Format output) {
		if (output != null || matches(output, outputFormats) != null) {
			RGBFormat inRGB = (RGBFormat) output;

			Dimension size = inRGB.getSize();
			int maxDataLength = inRGB.getMaxDataLength();
			int lineStride = inRGB.getLineStride();
			int flipped = inRGB.getFlipped();

			if (size == null)
				return null;

			if (maxDataLength < size.width * size.height * 3)
				maxDataLength = size.width * size.height * 3;

			if (lineStride < size.width * 3)
				lineStride = size.width * 3;

			if (flipped != Format.FALSE)
				flipped = Format.FALSE;

			outputFormat = outputFormats[0].intersects(new RGBFormat(size,
					maxDataLength, inRGB.getDataType(), inRGB.getFrameRate(),
					inRGB.getBitsPerPixel(), inRGB.getRedMask(), inRGB
							.getGreenMask(), inRGB.getBlueMask(), inRGB
							.getPixelStride(), lineStride, flipped, inRGB
							.getEndian()));

			return outputFormat;
		}

		return null;
	}

	/****** Codec ******/

	/****** PlugIn ******/
	public void close() {

	}

	public String getName() {
		return "Simple-Filter";
	}

	public void open() throws ResourceUnavailableException {

	}

	public void reset() {

	}

	/****** PlugIn ******/

	/****** Controls ******/
	public Object getControl(String controlType) {
		return null;
	}

	public Object[] getControls() {
		return null;
	}

	/****** Controls ******/

	/****** Utility ******/
	Format matches(Format in, Format outs[]) {
		for (int i = 0; i < outs.length; i++) {
			if (in.matches(outs[i]))
				return outs[i];
		}

		return null;
	}
	/****** Utility ******/
}